using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using NetQueryLib.Expressions;

namespace NetQueryLib
{
	internal class Chunker
	{
		private readonly Regex _pattern = new Regex(@"((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['""][^'""]*['""]|[^[\]'""]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?", 
		                                            RegexOptions.Compiled | RegexOptions.ECMAScript);
		private readonly SelectorExpression[] _currentSelectors;
		private int _currentChunkIndex;

		public Chunker(string selector, IEnumerable<SelectorExpressionBuilder> expressions)
		{
			_currentSelectors = _pattern.Matches(selector).Cast<Match>().Select(match => CreateSelectorExpression(match.Value, expressions)).ToArray();

			if(_currentSelectors.Length == 0)
				throw new ApplicationException("Could not load selectors!");
		}

		private static SelectorExpression CreateSelectorExpression(string selector, IEnumerable<SelectorExpressionBuilder> expressions)
		{
			foreach(var expr in expressions)
			{
				if (!expr.AppliesTo(selector))
					continue;

				return expr.Build(selector);
			}
			throw new NotImplementedException("Unrecognised expression " + selector);
		}

		public void Reset()
		{
			_currentChunkIndex = 0;
		}

		private bool LastChunk
		{
			get { return _currentChunkIndex == _currentSelectors.Length - 1; }
		}

		public SelectorExpression CurrentExpression
		{
			get { return _currentSelectors[_currentChunkIndex]; }
		}

		public bool MoveNext()
		{
			if(LastChunk)
				return false;

			_currentChunkIndex++;
			return true;
		}

		public bool Filter(XElement element)
		{
			return CurrentExpression.Filter(element);
		}
	}
}